TypeScript 93.3%
JavaScript 4.4%
CSS 2.3%
1/**2 * Author: Simon-Pierre Boucher3 * Contact: contact@spboucher.ai4 * Project: Hilmacorp.ai — Web Platform5 * File: app/[locale]/apps/page.tsx6 * Description: Apps page — web platforms (AI Risk Index, LLM Index) and the Zyquo family7 * of native macOS applications with direct DMG downloads8 */910import type { Metadata } from "next";11import Container from "@/components/Container";12import SectionHeading from "@/components/SectionHeading";13import { getMessages, isLocale, type Locale } from "@/lib/i18n";1415export async function generateMetadata({16 params,17}: {18 params: Promise<{ locale: string }>;19}): Promise<Metadata> {20 const { locale } = await params;21 if (!isLocale(locale)) return {};22 const { meta } = getMessages(locale);23 return { title: { absolute: meta.apps.title }, description: meta.apps.description };24}2526function CheckIcon() {27 return (28 <svg29 width="16"30 height="16"31 viewBox="0 0 16 16"32 fill="none"33 aria-hidden="true"34 className="mt-0.5 shrink-0"35 >36 <path37 d="M3 8.5l3.2 3L13 4.5"38 stroke="#0b6b4a"39 strokeWidth="1.8"40 strokeLinecap="round"41 strokeLinejoin="round"42 />43 </svg>44 );45}4647export default async function AppsPage({48 params,49}: {50 params: Promise<{ locale: string }>;51}) {52 const { locale } = await params;53 const { apps } = getMessages(locale as Locale);5455 return (56 <>57 <section className="relative overflow-hidden border-b border-line">58 <div className="grid-backdrop absolute inset-0" aria-hidden="true" />59 <Container className="relative py-20 sm:py-28">60 <SectionHeading as="h1" title={apps.title} lead={apps.lead} />61 </Container>62 </section>6364 {/* Web platforms */}65 <section className="py-16 sm:py-20">66 <Container>67 <SectionHeading title={apps.webTitle} lead={apps.webLead} />68 <div className="mt-10 grid gap-6 lg:grid-cols-2">69 {apps.web.map((app) => (70 <article71 key={app.id}72 className="flex flex-col rounded-3xl border border-line bg-card p-8 shadow-sm sm:p-10"73 >74 <p className="font-mono text-xs uppercase tracking-[0.2em] text-ink-faint">75 {app.urlLabel}76 </p>77 <h3 className="mt-3 font-display text-2xl font-semibold tracking-tight text-ink">78 {app.name}79 </h3>80 <p className="mt-2 font-medium text-accent">{app.tagline}</p>81 <p className="mt-4 leading-relaxed text-ink-soft">{app.description}</p>82 <ul className="mt-6 grid gap-2.5">83 {app.points.map((point) => (84 <li key={point} className="flex items-start gap-2.5 text-sm text-ink">85 <CheckIcon />86 {point}87 </li>88 ))}89 </ul>90 <div className="mt-8 flex-1" />91 <a92 href={app.url}93 target="_blank"94 rel="noopener noreferrer"95 className="inline-flex w-fit items-center gap-2 rounded-full bg-ink px-6 py-2.5 text-sm font-medium text-paper transition-colors hover:bg-accent-strong"96 >97 {apps.visit}98 <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">99 <path100 d="M4 10L10 4M10 4H5.5M10 4v4.5"101 stroke="currentColor"102 strokeWidth="1.6"103 strokeLinecap="round"104 strokeLinejoin="round"105 />106 </svg>107 </a>108 </article>109 ))}110 </div>111 </Container>112 </section>113114 {/* macOS apps */}115 <section className="border-t border-line bg-paper-2 py-16 sm:py-20">116 <Container>117 <SectionHeading title={apps.macTitle} lead={apps.macLead} />118 <div className="mt-10 grid gap-6 lg:grid-cols-2">119 {apps.mac.map((app) => (120 <article121 key={app.id}122 className="flex flex-col rounded-3xl border border-line bg-card p-8 shadow-sm sm:p-10"123 >124 <p className="font-mono text-xs uppercase tracking-[0.2em] text-ink-faint">125 {app.requires}126 </p>127 <h3 className="mt-3 font-display text-2xl font-semibold tracking-tight text-ink">128 {app.name}129 </h3>130 <p className="mt-2 font-medium text-accent">{app.tagline}</p>131 <p className="mt-4 leading-relaxed text-ink-soft">{app.description}</p>132 <ul className="mt-6 grid gap-2.5">133 {app.points.map((point) => (134 <li key={point} className="flex items-start gap-2.5 text-sm text-ink">135 <CheckIcon />136 {point}137 </li>138 ))}139 </ul>140 <div className="mt-8 flex-1" />141 <div className="flex flex-wrap items-center gap-4">142 <a143 href={`/downloads/${app.file}`}144 download145 className="inline-flex items-center gap-2 rounded-full bg-ink px-6 py-2.5 text-sm font-medium text-paper transition-colors hover:bg-accent-strong"146 >147 <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">148 <path149 d="M7 1.5v8m0 0L3.8 6.3M7 9.5l3.2-3.2M2 12.5h10"150 stroke="currentColor"151 strokeWidth="1.6"152 strokeLinecap="round"153 strokeLinejoin="round"154 />155 </svg>156 {apps.download}157 </a>158 <span className="font-mono text-xs text-ink-faint">{app.size}</span>159 </div>160 </article>161 ))}162 </div>163 <p className="mt-10 text-sm text-ink-faint">{apps.macNote}</p>164 </Container>165 </section>166 </>167 );168}169